/* 1. 动态类型 */
let a = 1;
a = '123';

/* 2. 隐式类型转换 */
let b = 1 + '23'; // b为：'123'

/* 3. 函数跟普通数据类型一样赋值给变量add */
let add = () => {
  let a = 1;
  return (b) => {
    return a + b;
  };
};
let add1 = add(); // add1和add2都是函数闭包
add1(2); // 输出为：3

/* 4. 对象与原型 */
let obj1 = {
  a: 1,
  add: function () {
    return this.a + this.b;
  }
};
let obj2 = {
  b: 2
};
// 设置obj2的原型为obj1
Object.setPrototypeOf(obj2, obj1);
obj2.add(); // 输出为：3


/*
pass 1
;; (b) => {

        enter_scope 1

;;     return a + b;

        line_num 12
        // a表示变量名称，1表示作用域层级
        scope_get_var a,1
        scope_get_var b,1
        add
        return

;;   }

pass 2
;; (b) => {
;;     return a + b;

        line_num 12
        get_var_ref_check 0: a
        get_arg 0: b
        add
        return

;;   }

./lab.js:11: function: <null>
  args: b
  closure vars:
    0: a local:loc0 let
  stack_size: 2
  opcodes:
;; (b) => {
;;     return a + b;

        get_var_ref_check 0: a
        get_arg0 0: b
        add
        return

;;   }
*/

/*
pass 1
;; () => {

        enter_scope 1

;;   let a = 1;

        line_num 10
        push_i32 1
        scope_put_var_init a,1

;;   return (b) => {
;;     return a + b;
;;   };

        line_num 13
        fclosure 0: [bytecode <null>]
        set_name "<null>"
        return

;; }

pass 2
;; () => {

        set_loc_uninitialized 0: a

;;   let a = 1;

        line_num 10
        push_i32 1
        put_loc 0: a

;;   return (b) => {
;;     return a + b;
;;   };

        line_num 13
        fclosure 0: [bytecode <null>]
        return

;; }

./lab.js:9: function: <null>
  locals:
    0: let a [level:1 next:-1]
  stack_size: 1
  opcodes:
;; () => {

        set_loc_uninitialized 0: a

;;   let a = 1;

        push_1 1
        put_loc0 0: a

;;   return (b) => {
;;     return a + b;
;;   };

        fclosure8 0: [bytecode <null>]
        return

;; }
*/

/*
pass 1
;; function () {

        enter_scope 1

;;     return this.a + this.b;

        line_num 22
        scope_get_var this,0
        get_field a
        scope_get_var this,0
        get_field b
        add
        return

;;   }

pass 2
;; function () {
;;     return this.a + this.b;

        line_num 22
        get_loc 0: this
        get_field a
        get_loc 0: this
        get_field b
        add
        return

;;   }

./lab.js:21: function: <null>
  locals:
    0: var this
  stack_size: 2
  opcodes:
;; function () {

        push_this
        put_loc0 0: this

;;     return this.a + this.b;

        get_loc0 0: this
        get_field a
        get_loc0 0: this
        get_field b
        add
        return

;;   }
*/

/*
pass 1
        line_num 0
        enter_scope 1
        line_num 2
        push_i32 1
        scope_put_var_init a,1
        line_num 3
        scope_make_ref a,0:51,1
        push_const 0: 1"123"
        label 0:51
   51:  insert3
        put_ref_value
        put_loc 0: "<ret>"
        line_num 6
        push_i32 1
        push_const 1: 1"23"
        add
        scope_put_var_init b,1
        line_num 14
        fclosure 2: [bytecode <null>]
        set_name add
        scope_put_var_init add,1
        line_num 15
        scope_get_var add,1
        call 0
        scope_put_var_init add1,1
        line_num 16
        scope_get_var add1,1
        push_i32 2
        call 1
        put_loc 0: "<ret>"
        line_num 19
        object
        line_num 20
        push_i32 1
        define_field a
        line_num 23
        fclosure 3: [bytecode <null>]
        set_name add
        define_field add
        line_num 24
        scope_put_var_init obj1,1
        line_num 25
        object
        line_num 26
        push_i32 2
        define_field b
        line_num 27
        scope_put_var_init obj2,1
        line_num 29
        scope_get_var Object,1
        get_field2 setPrototypeOf
        scope_get_var obj2,1
        scope_get_var obj1,1
        call_method 2
        put_loc 0: "<ret>"
        line_num 30
        scope_get_var obj2,1
        get_field2 add
        call_method 0
        put_loc 0: "<ret>"
        get_loc 0: "<ret>"
        return

pass 2
        check_define_var a,128
        check_define_var b,128
        check_define_var add,128
        check_define_var add1,128
        check_define_var obj1,128
        check_define_var obj2,128
        line_num 0
        define_var a,130
        define_var b,130
        define_var add,130
        define_var add1,130
        define_var obj1,130
        define_var obj2,130
        line_num 2
        push_i32 1
        put_var_init a
        line_num 3
        push_const 0: 1"123"
        dup
        put_var a
        put_loc 0: "<ret>"
        line_num 6
        push_i32 1
        push_const 1: 1"23"
        add
        put_var_init b
        line_num 14
        fclosure 2: [bytecode <null>]
        set_name add
        put_var_init add
        line_num 15
        get_var add
        call 0
        put_var_init add1
        line_num 16
        get_var add1
        push_i32 2
        call 1
        put_loc 0: "<ret>"
        line_num 19
        object
        line_num 20
        push_i32 1
        define_field a
        line_num 23
        fclosure 3: [bytecode <null>]
        set_name add
        define_field add
        line_num 24
        put_var_init obj1
        line_num 25
        object
        line_num 26
        push_i32 2
        define_field b
        line_num 27
        put_var_init obj2
        line_num 29
        get_var Object
        get_field2 setPrototypeOf
        get_var obj2
        get_var obj1
        call_method 2
        put_loc 0: "<ret>"
        line_num 30
        get_var obj2
        get_field2 add
        call_method 0
        put_loc 0: "<ret>"
        get_loc 0: "<ret>"
        return

./lab.js:1: function: <eval>
  locals:
    0: var <ret>
  stack_size: 4
  opcodes:
        check_define_var a,128
        check_define_var b,128
        check_define_var add,128
        check_define_var add1,128
        check_define_var obj1,128
        check_define_var obj2,128
        define_var a,130
        define_var b,130
        define_var add,130
        define_var add1,130
        define_var obj1,130
        define_var obj2,130
        push_1 1
        put_var_init a
        push_const8 0: 1"123"
        dup
        put_var a
        put_loc0 0: "<ret>"
        push_1 1
        push_const8 1: 1"23"
        add
        put_var_init b
        fclosure8 2: [bytecode <null>]
        set_name add
        put_var_init add
        get_var add
        call0 0
        put_var_init add1
        get_var add1
        push_2 2
        call1 1
        put_loc0 0: "<ret>"
        object
        push_1 1
        define_field a
        fclosure8 3: [bytecode <null>]
        set_name add
        define_field add
        put_var_init obj1
        object
        push_2 2
        define_field b
        put_var_init obj2
        get_var Object
        get_field2 setPrototypeOf
        get_var obj2
        get_var obj1
        call_method 2
        put_loc0 0: "<ret>"
        get_var obj2
        get_field2 add
        call_method 0
        set_loc0 0: "<ret>"
        return
 */
